//*****************************************************************************
//
//									SPI.c
//
//*****************************************************************************
//
//
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "printf.h"
#include "I2C.h"
#include "CPU.h"
#include "SPI.h"

//----------------- SPI Mode Definition ---------------------
/*
#if		( SPI_READ_MODE == SPI_READ_SLOW )

	#define DMAMODE_READ_FIX		0xe4
	#define DMAMODE_READ_INC 		0xc4
	#define DMAMODE_WRITE_FIX		0xe4
	#define DMAMODE_WRITE_INC		0xc4

	#define SPICMD_READ				0x03
	#define SPICMD_PROGRAM			0x02


#elif	( SPI_READ_MODE == SPI_READ_QUADIO )

	#define DMAMODE_READ_FIX		0xe7
	#define DMAMODE_READ_INC 		0xc7
	#define DMAMODE_WRITE_FIX		0xe7
	#define DMAMODE_WRITE_INC		0xc7

	#define SPICMD_READ				0xeb
	#define SPICMD_PROGRAM			0x02

#elif	( SPI_READ_MODE == SPI_READ_DUALIO )

#endif
*/

#ifdef address_32bit  //erek for 4byte address spi, 20121214
BYTE DMAMODE_RW_FIX_REG = 0xe5;
BYTE DMAMODE_RW_INC_REG = 0xc5;
BYTE DMAMODE_RW_XDATA   = 0x85;

BYTE SPICMD_READ        = 0x03;
BYTE SPICMD_PROGRAM     = 0x02;


//=============================================================================
//
//=============================================================================
BYTE SPI_SetModeByRegister( void )
{
	BYTE mod;

	WriteTW88( 0xff, SPI_PAGE );
	mod = ReadTW88( 0x00 ) & 0x07;

	switch( mod ) {
		case 0:	//--- Slow
			DMAMODE_RW_FIX_REG = 0xe5;
			DMAMODE_RW_INC_REG = 0xc5;
			DMAMODE_RW_XDATA   = 0x85;
			SPICMD_READ        = 0x03;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 1:	//--- Fast
			DMAMODE_RW_FIX_REG = 0xe6;
			DMAMODE_RW_INC_REG = 0xc6;
			DMAMODE_RW_XDATA   = 0x86;
			SPICMD_READ        = 0x0b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 2:	//--- Dual
			DMAMODE_RW_FIX_REG = 0xe6;
			DMAMODE_RW_INC_REG = 0xc6;
			DMAMODE_RW_XDATA   = 0x86;
			SPICMD_READ        = 0x3b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 3:	//--- Quad
			DMAMODE_RW_FIX_REG = 0xe6;
			DMAMODE_RW_INC_REG = 0xc6;
			DMAMODE_RW_XDATA   = 0x86;
			SPICMD_READ        = 0x6b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 4:	//--- Dual-IO
			DMAMODE_RW_FIX_REG = 0xe6;
			DMAMODE_RW_INC_REG = 0xc6;
			DMAMODE_RW_XDATA   = 0x86;
			SPICMD_READ        = 0xbb;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 5:	//--- Quad-IO
			DMAMODE_RW_FIX_REG = 0xe8;
			DMAMODE_RW_INC_REG = 0xc8;
			DMAMODE_RW_XDATA   = 0x88;
			SPICMD_READ        = 0xeb;
			SPICMD_PROGRAM     = 0x02;
			break;
 	}
	return mod;
}

#else
BYTE DMAMODE_RW_FIX_REG = 0xe4;
BYTE DMAMODE_RW_INC_REG = 0xc4;
BYTE DMAMODE_RW_XDATA   = 0x84;

BYTE SPICMD_READ        = 0x03;
BYTE SPICMD_PROGRAM     = 0x02;


//=============================================================================
//
//=============================================================================
BYTE SPI_SetModeByRegister( void )
{
	BYTE mod;

	WriteTW88( 0xff, SPI_PAGE );
	mod = ReadTW88( 0x00 ) & 0x07;

	switch( mod ) {
		case 0:	//--- Slow
			DMAMODE_RW_FIX_REG = 0xe4;
			DMAMODE_RW_INC_REG = 0xc4;
			DMAMODE_RW_XDATA   = 0x84;
			SPICMD_READ        = 0x03;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 1:	//--- Fast
			DMAMODE_RW_FIX_REG = 0xe5;
			DMAMODE_RW_INC_REG = 0xc5;
			DMAMODE_RW_XDATA   = 0x85;
			SPICMD_READ        = 0x0b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 2:	//--- Dual
			DMAMODE_RW_FIX_REG = 0xe5;
			DMAMODE_RW_INC_REG = 0xc5;
			DMAMODE_RW_XDATA   = 0x85;
			SPICMD_READ        = 0x3b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 3:	//--- Quad
			DMAMODE_RW_FIX_REG = 0xe5;
			DMAMODE_RW_INC_REG = 0xc5;
			DMAMODE_RW_XDATA   = 0x85;
			SPICMD_READ        = 0x6b;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 4:	//--- Dual-IO
			DMAMODE_RW_FIX_REG = 0xe5;
			DMAMODE_RW_INC_REG = 0xc5;
			DMAMODE_RW_XDATA   = 0x85;
			SPICMD_READ        = 0xbb;
			SPICMD_PROGRAM     = 0x02;
			break;

		case 5:	//--- Quad-IO
			DMAMODE_RW_FIX_REG = 0xe7;
			DMAMODE_RW_INC_REG = 0xc7;
			DMAMODE_RW_XDATA   = 0x87;
			SPICMD_READ        = 0xeb;
			SPICMD_PROGRAM     = 0x02;
			break;
 	}
	return mod;
}
#endif

BYTE	SaveReg00, SaveReg01, SaveReg02, SaveReg20;

//=============================================================================
//
//=============================================================================
void SPI_SetAccess( void )
{
	WriteTW88( 0xff, SPI_PAGE );
	SaveReg00 = ReadTW88( 0x00 );
	SaveReg01 = ReadTW88( 0x01 );
	SaveReg02 = ReadTW88( 0x02 );
	WriteTW88( 0x02, SaveReg02 & 0xCF );
	WriteTW88( 0x01, SaveReg01 & 0xCF );
	WriteTW88( 0x00, SaveReg00 & 0xF8 );

	SaveReg20 = ReadTW88( 0x20 );

	WriteTW88( 0x20, SaveReg20 & 0xDB );	   	// OSD DMA, cache off

	SPI_SetModeByRegister();
}

void SPI_RevertAccess(void)
{
	WriteTW88( 0x00, SaveReg00 );
	WriteTW88( 0x01, SaveReg01 );
	WriteTW88( 0x02, SaveReg02 );
	WriteTW88( 0x20, SaveReg20 );

	SPI_SetModeByRegister();
}

void SPI_Init(void)
{
//	BYTE dat;

	WriteTW88( 0xff, SPI_PAGE );
	//Printf("\n\r Enter SPI Turbo1\n");
	WriteTW88( 0x00, SPI_READ_MODE );			// SPI Mode:	0=Slow, 1=fast, 2=dual, 3=quad, 4=dual-io, 5=quad-io

		WriteTW88( 0x01, 0x06 );					// MCU Clock:	27MHz
		WriteTW88( 0x02, 0x06 );					// SPI Clock:	27MHz
	
	//	Printf("\n\r Enter SPI Turbo1\n");


//	dat = ReadTW88( 0x20 ) | 0x2c;				//----- Enable OSD-DMA, Cache
//	WriteTW88( 0x20, dat );

	SPI_SetModeByRegister();					// Match DMA mode with SPI-read

}


//=============================================================================
//
//=============================================================================
#define		MCU_108					// 0E30
//#define		MCU_72					// 14C0
//#define		MCU_54					// 1B40
//#define		MCU_43					// 1F80
//#define		MCU_36			   		// 2530
//#define		MCU_30					// 2A20	-> 29D8
//#define		MCU_27				 	// 3100	-> 2CC0
//#define		MCU_13		
#ifdef DP80390
void SPI_TurboInit(void)
{
	BYTE	MCU_PLL;

	MCU_PLL = 0;							
	WriteTW88( 0xff, SPI_PAGE );

	WriteTW88( 0x00, SPI_READ_QUADIO );			// SPI Mode:	0=Slow, 1=fast, 2=dual, 3=quad, 4=dual-io, 5=quad-io

#ifdef		MCU_108
	WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
	WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_72
	WriteTW88( 0x01, 0x01 );					// change PLL divider as 72MHz
	WriteTW88( 0x01, 0x21 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_54
	WriteTW88( 0x01, 0x02 );					// change PLL divider as 54MHz
	WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_43
	WriteTW88( 0x01, 0x03 );					// change PLL divider as 43MHz
	WriteTW88( 0x01, 0x23 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_36
	WriteTW88( 0x01, 0x04 );					// change PLL divider as 36MHz
	WriteTW88( 0x01, 0x24 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_30
	WriteTW88( 0x01, 0x05 );					// change PLL divider as 30MHz
	WriteTW88( 0x01, 0x25 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_27
	WriteTW88( 0x01, 0x06 );					// change PLL divider as 27MHz
	WriteTW88( 0x01, 0x26 );					// change MCU clock : Xtal -> PLL div
#endif
#ifdef		MCU_13
	WriteTW88( 0x01, 0x07 );					// change PLL divider as 13MHz
	WriteTW88( 0x01, 0x27 );					// change MCU clock : Xtal -> PLL div
#endif
	
	//WriteTW88( 0x02, 0x03 );					// change PLL divider as 43MHz
	//WriteTW88( 0x02, 0x23 );					// change SPI Clock: Xtal -> PLL div
	WriteTW88( 0x02, 0x02 );					// change PLL divider as 54MHz
	WriteTW88( 0x02, 0x22 );					// change SPI Clock: Xtal -> PLL div
	
	SPI_SetModeByRegister();					// Match DMA mode with SPI-read

	//WriteTW88( 0x20, (ReadTW88( 0x20 ) | 0x20) );				//----- Enable OSD DMA
	//WriteTW88( 0x20, (ReadTW88( 0x20 ) | 0x24) );				//----- Enable Cache & OSD DMA
	WriteTW88(0x20, (ReadTW88(0x20) | 0x04));				//----- Enable Cache

	MCU_PLL = 0;
	while (++MCU_PLL)
	{
		I2C_SCL = 0;
		I2C_SCL = 1;
		I2C_SCL = 0;
		I2C_SCL = 1;
	}
}
#else
WORD	CheckSpeed(void)
{
	WORD	i;

	EA=0;
	
	TR2 = 0;		// stop timer
	TL2 = TH2 = 0;
	TR2 = 1;		// run timer
	i = 0;
	while (TL2<100) {
		i++;
	}
	TR2 = 0;		// stop timer

	EA=1;
	
	Printf("\nCount0: %x", i);
	return i;
}


void SPI_TurboInit(void)
{
	WORD	i;
	
		WriteTW88( 0xff, SPI_PAGE );
		Puts("\n SPI_TurboInit");
		WriteTW88( 0x00, SPI_READ_QUADIO ); 		// SPI Mode:	0=Slow, 1=fast, 2=dual, 3=quad, 4=dual-io, 5=quad-io
		Puts("\n SPI_READ_QUADIO");
	
	
		WriteTW88(0x26, 0xd2);		// 1 MHz clock for 108MHz MCU
		WriteTW88(0x27, 0xf0);		//	
#ifdef		MCU_108
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88(0x22, 0xd2);						// 13500 -> 54000 for timer tick0
		WriteTW88(0x23, 0xf0);						//
		i = CheckSpeed();
		/*while ( i > 0x1000 ) {
		//while ( i ) {
			WriteTW88( 0x01, 0x21 );					// change PLL divider as 72MHz
			WriteTW88( 0x01, 0x20 );					// change PLL divider as 108MHz
			i = CheckSpeed();
		}*/
#endif
#ifdef		MCU_72
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x21 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x21 );					// change MCU clock : Xtal -> PLL div
		WriteTW88(0x22, 0x8c);						// 13500 -> 36000 for timer tick0
		WriteTW88(0x23, 0xa0);						//
		i = CheckSpeed();
		while (( i > 0x1800 )||( i < 0x1000 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x21 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_54
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x23 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
		WriteTW88(0x22, 0x69);						// 13500 -> 27000 for timer tick0
		WriteTW88(0x23, 0x78);						//
		i = CheckSpeed();
		while (( i > 0x1D00 )||( i < 0x1800 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x23 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x22 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_43
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x23 );					// change PLL divider as 43MHz
		WriteTW88( 0x01, 0x24 );					// change PLL divider as 43MHz
		WriteTW88( 0x01, 0x23 );					// change PLL divider as 43MHz
		WriteTW88(0x22, 0x54);						// 13500 -> 21600 for timer tick0
		WriteTW88(0x23, 0x60);						//
		i = CheckSpeed();
		while (( i > 0x2200 )||( i < 0x1D00 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x24 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x23 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_36
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x24 );					// change PLL divider as 36MHz
		WriteTW88( 0x01, 0x25 );					// change PLL divider as 36MHz
		WriteTW88( 0x01, 0x24 );					// change PLL divider as 36MHz
		WriteTW88(0x22, 0x46);						// 13500 -> 18000 for timer tick0
		WriteTW88(0x23, 0x50);						//
		i = CheckSpeed();
		while (( i > 0x2800 )||( i < 0x2200 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x25 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x24 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_30
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x25 );					// change PLL divider as 30MHz
		WriteTW88( 0x01, 0x26 );					// change PLL divider as 30MHz
		WriteTW88( 0x01, 0x25 );					// change PLL divider as 30MHz
		WriteTW88(0x22, 0x3c);						// 13500 -> 15428 for timer tick0
		WriteTW88(0x23, 0x44);						//
		i = CheckSpeed();
		while (( i > 0x2C00 )||( i < 0x2800 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x26 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x25 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_27
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x26 );					// change PLL divider as 27MHz
		WriteTW88( 0x01, 0x27 );					// change PLL divider as 27MHz
		WriteTW88( 0x01, 0x26 );					// change PLL divider as 27MHz
	
		WriteTW88(0x22, 0x34);						// 13500 for timer tick0
		WriteTW88(0x23, 0xbc);						//
		i = CheckSpeed();
		while (( i > 0x3300 )||( i < 0x2B00 )) {
		//while ( i ) {
			WriteTW88( 0x01, 0x27 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x26 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
#ifdef		MCU_13
		WriteTW88( 0x01, 0x00 );					// change PLL divider as 108MHz
		WriteTW88( 0x01, 0x20 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x27 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x26 );					// change MCU clock : Xtal -> PLL div
		WriteTW88( 0x01, 0x27 );					// change MCU clock : Xtal -> PLL div
		WriteTW88(0x22, 0x1a);						// 6750 for timer tick0
		WriteTW88(0x23, 0x5e);						//
		i = CheckSpeed();
		while ( i < 0x3300 ) {
		//while ( i ) {
			WriteTW88( 0x01, 0x26 );					// change MCU clock : Xtal -> PLL div
			WriteTW88( 0x01, 0x27 );					// change MCU clock : Xtal -> PLL div
			i = CheckSpeed();
		}
#endif
		Puts("\n MCU Clock set to PLL");
	
	
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
		WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
		WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
	
		do {
			WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
			WriteTW88( 0x02, 0x03 );					// change SPI Clock: 43MHz
			WriteTW88( 0x02, 0x02 );					// change SPI Clock: 54MHz
			//Puts("\n SPI Clock set to PLL");
			WriteTW88( 0x02, 0x22 );					// change SPI Clock: 54MHz
		} while ( CheckSpeed() < 0x1500 );					// i = 1400 for 43MHz
	
		Puts("\n SPI Clock set");
	
		SPI_SetModeByRegister();					// Match DMA mode with SPI-read
	
		//WriteTW88( 0x20, (ReadTW88( 0x20 ) | 0x20) ); 			//----- Enable OSD DMA
		//WriteTW88( 0x20, (ReadTW88( 0x20 ) | 0x24) ); 			//----- Enable Cache & OSD DMA
		WriteTW88( 0x20, (ReadTW88( 0x20 ) | 0x04) );				//----- Enable Cache
		Puts("\n Enable cache");
	
}
#endif

void SPI_QUADInit(void)
{
	BYTE temp, chid;

	WriteTW88(0xff, SPI_PAGE);

	WriteTW88(0x03, 0x41);						// mode, cmd-len 1
	WriteTW88(0x0a, 0x9f);						// cmd, read Jedec ID

	WriteTW88(0x1a, 0);
	WriteTW88(0x08, 0);
	WriteTW88(0x09, 3);							// read buffer size 3
	WriteTW88(0x04, 0x01);						// start

	temp = ReadTW88(0x10);
	chid = ReadTW88(0x12);
	//Printf("\nSPI JEDEC ID: %02bx %02bx %02bx", temp, ReadTW88(0x11), ReadTW88(0x12));

	if (temp == 0xC2)							// for MX
	{
		WriteTW88(0x03, 0x41);					// mode, cmd-len 1
		WriteTW88(0x0a, 0x05);					// cmd, read Status
		WriteTW88(0x09, 1);						// read buffer size 1
		WriteTW88(0x04, 0x01);					// start

		temp = ReadTW88(0x10);					// read status regisiter value
		if (temp == 0)
		{
			//Puts("\nEnable MX quad mode" );
			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x06);				// cmd, write enable
			WriteTW88(0x09, 0);					// read buffer size 1
			WriteTW88(0x04, 0x03);				// start

			//Puts("\nWrite ENABLED" );

			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x05);				// cmd, read Status
			WriteTW88(0x09, 1);					// read buffer size 1
			WriteTW88(0x04, 0x01);				// start
			temp = ReadTW88(0x10);				// read status regisiter value
			//Printf("\nStatus after Write enable %02bx", temp );

			WriteTW88(0x03, 0x42);				// mode, cmd-len 2
			WriteTW88(0x0a, 0x01);				// cmd, write Status
			WriteTW88(0x0b, 0x40);				// cmd, en QAUD mode
			WriteTW88(0x09, 0);					// read buffer size 1
			WriteTW88(0x04, 0x07);				// start + write + busycheck

			//Puts("\nQUAD ENABLED" );

			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x05);				// cmd, read Status
			WriteTW88(0x09, 1);					// read buffer size 1
			WriteTW88(0x04, 0x01);				// start
			temp = ReadTW88(0x10);				// read status regisiter value
			//Printf("\nStatus after QUAD enable %02bx", temp );

			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x06);				// cmd, write disable
			WriteTW88(0x04, 0x01);				// start
		}
	}
	else if (temp == 0xEF)						// for WB
	{
		WriteTW88(0x03, 0x41);					// mode, cmd-len 1
		WriteTW88(0x0a, 0x05);					// cmd, read Status
		WriteTW88(0x09, 2);						// read buffer size 1
		WriteTW88(0x04, 0x01);					// start

		temp = ReadTW88(0x11);					// read status regisiter value
		if (temp == 0)
		{
			//Puts("\nEnable WB quad mode" );
			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x06);				// cmd, write enable
			WriteTW88(0x04, 0x01);				// start

			WriteTW88(0x03, 0x43);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x01);				// cmd, write Status
			WriteTW88(0x0b, 0x00);				// cmd, en QAUD mode
			WriteTW88(0x0c, 0x02);				// cmd, en QAUD mode
			WriteTW88(0x04, 0x01);				// start
		}
	}
	else if (temp == 0x20)						// for MICRON
	{
		if (chid == 0x18)						// Q128 case different status read command
		{
			// set Volatile
			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0x85);				// cmd, read Volatile register
			WriteTW88(0x09, 1);					// read buffer size 1
			WriteTW88(0x04, 0x01);				// start

			temp = ReadTW88(0x10);				// read Volatile  regisiter value
			//dPrintf("\nVolatile Register: %02bx", ReadTW88( 0x10 ) );
			if (temp != 0x6B)
			{
				WriteTW88(0x09, 0);				// read buffer size 0
				WriteTW88(0x03, 0x41);			// mode, cmd-len 1
				WriteTW88(0x0a, 0x06);			// cmd, write enable
				WriteTW88(0x04, 0x01);			// start

				WriteTW88(0x03, 0x42);			// mode, cmd-len 2
				WriteTW88(0x0a, 0x81);			// cmd, write Volatile
				WriteTW88(0x0b, 0x6B);			// set 6 dummy cycles
				WriteTW88(0x04, 0x07);			// start 7 busycheck
				//dPuts("\nVolatile 6 dummy SET");
			}
			// set non-Volatile
			WriteTW88(0x03, 0x41);				// mode, cmd-len 1
			WriteTW88(0x0a, 0xB5);				// cmd, read Status
			WriteTW88(0x09, 2);					// read buffer size 2
			WriteTW88(0x04, 0x01);				// start

			temp = ReadTW88(0x11);				// read NV regisiter value
			//dPrintf("\nNon-Volatile REgister: %02bx, %02bx", ReadTW88( 0x10 ), ReadTW88( 0x11 ) );
			if (temp != 0x6F)
			{
				WriteTW88(0x09, 0);				// read buffer size 0
				WriteTW88(0x03, 0x41);			// mode, cmd-len 1
				WriteTW88(0x0a, 0x06);			// cmd, write enable
				WriteTW88(0x04, 0x01);			// start

				WriteTW88(0x03, 0x43);			// mode, cmd-len 3
				WriteTW88(0x0a, 0xB1);			// cmd, write Non Volatile
				WriteTW88(0x0b, 0xFF);			// cmd, B7~B0
				WriteTW88(0x0c, 0x6F);			// cmd, B15~B8
				WriteTW88(0x04, 0x07);			// start 7 busycheck
				//dPuts("\nnon-Volatile 6 dummy SET");
			}
		//dPuts("\nDone!!!");
		}
	}
/*
	else if (temp == 0x)						// for GigaDevice
	{
	}
*/
}

#ifdef address_32bit  //erek for 4byte address spi, 20121214

void SPI_Addr32Enable(void)
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	WriteTW88( 0x03, 0x41 );					// Mode = command write, Len=1
	WriteTW88( 0x0a, 0xb7 );					// SPI Command = 4byte_address_ENABLE
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x03 );					// DMA-Write start
}

void SPI_Addr32Disable(void)
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	WriteTW88( 0x03, 0x41 );					// Mode = command write, Len=1
	WriteTW88( 0x0a, 0xe9 );					// SPI Command = 4byte_address_ENABLE
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x03 );					// DMA-Write start
}

//=============================================================================
//		SPI DMA (SPI --> Fixed Register)
//=============================================================================
void SPI_ReadData2Reg( DWORD spiaddr, WORD index, DWORD cnt )
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	//SPI_Addr32Enable();
	//Printf("\r\n DMAMODE_RW_FIX_REG=%bx",DMAMODE_RW_FIX_REG);
	//Printf("\r\n SPICMD_READ=%bx",SPICMD_READ);

	if((DMAMODE_RW_FIX_REG<<4)>=0x80)
	{
		WriteTW88( 0x1c, (ReadTW88(0x1c))|0x08);		// Mode = SPI -> fixed register
		WriteTW88( 0x03, (DMAMODE_RW_FIX_REG&0xf7));		// Mode = SPI -> fixed register
		
	}
	WriteTW88( 0x0a, SPICMD_READ );				// Read Command
	WriteTW88( 0x0b, spiaddr>>24 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0d, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0e, spiaddr );					// SPI address
	WriteTW88( 0x06, index>>8 );				// Buffer address
	WriteTW88( 0x07, index );					// Buffer address
	WriteTW88( 0x1a, cnt>>16 );					// Read count
	WriteTW88( 0x08, cnt>>8 );					// Read count
	WriteTW88( 0x09, cnt );						// Read count
	
	WriteTW88( 0x04, 0x01 );					// DMA-Read start
}

//=============================================================================
//		SPI DMA (SPI --> Incremental XDATA)
//=============================================================================
void SPI_ReadData2xdata( DWORD spiaddr, BYTE *ptr, DWORD cnt )
{
	WORD xaddr = (WORD)ptr;

	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	//SPI_Addr32Enable();

	//SPI_SetAccess();

	//Printf("\r\n DMAMODE_RW_FIX_REG=%bx",DMAMODE_RW_XDATA);
	//Printf("\r\n SPICMD_READ=%bx",SPICMD_READ);

	if ((DMAMODE_RW_XDATA<<4) >= 0x80)
	{
		WriteTW88( 0x03, (DMAMODE_RW_XDATA&0xf7));		// Mode = SPI -> incremental xdata
		WriteTW88( 0x1c, (ReadTW88(0x1c))|0x08);		// Mode = SPI -> fixed register
	}

	WriteTW88( 0x0a, SPICMD_READ );				// Read Command
	WriteTW88( 0x0b, spiaddr>>24 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0d, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0e, spiaddr );					// SPI address
 	WriteTW88( 0x06, xaddr>>8 );				// Buffer address
	WriteTW88( 0x07, xaddr );					// Buffer address
	WriteTW88( 0x1a, cnt>>16 );					// Read count
 	WriteTW88( 0x08, cnt>>8 );					// Read count
	WriteTW88( 0x09, cnt );						// Read count

	WriteTW88( 0x04, 0x01 );					// DMA-Read start

	//SPI_RevertAccess();
}

//=============================================================================
//		SPI Write Enable
//=============================================================================
void SPI_WriteEnable(void)
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	WriteTW88( 0x03, 0x41 );					// Mode = command write, Len=1
	WriteTW88( 0x0a, 0x06 );					// SPI Command = WRITE_ENABLE
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x03 );					// DMA-Write start
}

//=============================================================================
//		SPI Sector Erase
//=============================================================================
void SPI_SectorErase(DWORD spiaddr)
{
	SPI_WriteEnable();

	WriteTW88( 0x03, 0x45 );					// Mode = command write, Len=4
	WriteTW88( 0x0a, 0x20 );					// SPI Command = SECTOR_ERASE
	WriteTW88( 0x0b, spiaddr>>24 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0d, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0e, spiaddr );					// SPI address
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

//=============================================================================
//		SPI Block Erase
//=============================================================================
void SPI_BlockErase( DWORD spiaddr )
{
	SPI_WriteEnable();

	WriteTW88( 0x03, 0x45 );					// Mode = command write, Len=4
	WriteTW88( 0x0a, 0xd8 );					// SPI Command = BLOCK_ERASE
	WriteTW88( 0x0b, spiaddr>>24 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0d, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0e, spiaddr );					// SPI address
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

//=============================================================================
//		SPI PageProgram
//=============================================================================
void SPI_PageProgram( DWORD spiaddr, BYTE *ptr, WORD cnt )
{
	WORD xaddr = (WORD)ptr;

	SPI_WriteEnable();

	if((DMAMODE_RW_XDATA<<4)>=0x80)
	{
		WriteTW88( 0x03, (DMAMODE_RW_XDATA&0xf7));		// Mode = SPI -> incremental xdata
		WriteTW88( 0x1c, (ReadTW88(0x1c))|0x08);		// Mode = SPI -> fixed register
	}

	WriteTW88( 0x03, DMAMODE_RW_XDATA );		// Mode = xdata -> SPI, Len=4
	WriteTW88( 0x0a, SPICMD_PROGRAM );			// SPI Command = PAGE_PROGRAM
	WriteTW88( 0x0b, spiaddr>>24 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0d, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0e, spiaddr );					// SPI address
 	WriteTW88( 0x06, xaddr>>8 );				// Buffer address
	WriteTW88( 0x07, xaddr );					// Buffer address
 	WriteTW88( 0x08, cnt>>8 );					// Write count
	WriteTW88( 0x09, cnt );						// Write count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

#else
//=============================================================================
//		SPI DMA (SPI --> Fixed Register)
//=============================================================================
void SPI_ReadData2Reg( DWORD spiaddr, WORD index, DWORD cnt )
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5
	//Printf("\r\n DMAMODE_RW_FIX_REG=%bx",DMAMODE_RW_FIX_REG);
	//Printf("\r\n SPICMD_READ=%bx",SPICMD_READ);

	WriteTW88( 0x03, DMAMODE_RW_FIX_REG);		// Mode = SPI -> fixed register
	WriteTW88( 0x0a, SPICMD_READ );				// Read Command
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
	WriteTW88( 0x06, index>>8 );				// Buffer address
	WriteTW88( 0x07, index );					// Buffer address
	WriteTW88( 0x1a, cnt>>16 );					// Read count
	WriteTW88( 0x08, cnt>>8 );					// Read count
	WriteTW88( 0x09, cnt );						// Read count
	
	WriteTW88( 0x04, 0x01 );					// DMA-Read start
}

//=============================================================================
//		SPI DMA (SPI --> Incremental Register)
//=============================================================================
/*
void SPI_ReadData2RegInc( DWORD spiaddr, WORD index, DWORD cnt )
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	WriteTW88( 0x03, DMAMODE_RW_INC_REG );		// Mode = SPI -> incremental register
	WriteTW88( 0x0a, SPICMD_READ );				// Read Command
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
 	WriteTW88( 0x06, index>>8 );				// Buffer address
	WriteTW88( 0x07, index );					// Buffer address
	WriteTW88( 0x1a, cnt>>16 );					// Read count
 	WriteTW88( 0x08, cnt>>8 );					// Read count
	WriteTW88( 0x09, cnt );						// Read count

	WriteTW88( 0x04, 0x01 );					// DMA-Read start
}
*/

//=============================================================================
//		SPI DMA (SPI --> Incremental XDATA)
//=============================================================================
void SPI_ReadData2xdata( DWORD spiaddr, BYTE *ptr, DWORD cnt )
{
	WORD xaddr = (WORD)ptr;

	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5
	//Printf("\r\n DMAMODE_RW_FIX_REG=%bx",DMAMODE_RW_XDATA);
	//Printf("\r\n SPICMD_READ=%bx",SPICMD_READ);

	WriteTW88( 0x03, DMAMODE_RW_XDATA );		// Mode = SPI -> incremental xdata
	WriteTW88( 0x0a, SPICMD_READ );				// Read Command
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
 	WriteTW88( 0x06, xaddr>>8 );				// Buffer address
	WriteTW88( 0x07, xaddr );					// Buffer address
	WriteTW88( 0x1a, cnt>>16 );					// Read count
 	WriteTW88( 0x08, cnt>>8 );					// Read count
	WriteTW88( 0x09, cnt );						// Read count

	WriteTW88( 0x04, 0x01 );					// DMA-Read start
}

//=============================================================================
//		SPI Write Enable
//=============================================================================
void SPI_WriteEnable(void)
{
	WriteTW88( 0xff, SPI_PAGE );				// Set Page=5

	WriteTW88( 0x03, 0x41 );					// Mode = command write, Len=1
	WriteTW88( 0x0a, 0x06 );					// SPI Command = WRITE_ENABLE
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x03 );					// DMA-Write start
}

//=============================================================================
//		SPI Sector Erase
//=============================================================================
void SPI_SectorErase( DWORD spiaddr )
{
	SPI_WriteEnable();

	WriteTW88( 0x03, 0x44 );					// Mode = command write, Len=4
	WriteTW88( 0x0a, 0x20 );					// SPI Command = SECTOR_ERASE
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

//=============================================================================
//		SPI Block Erase
//=============================================================================
void SPI_BlockErase( DWORD spiaddr )
{
	SPI_WriteEnable();

	WriteTW88( 0x03, 0x44 );					// Mode = command write, Len=4
	WriteTW88( 0x0a, 0xd8 );					// SPI Command = BLOCK_ERASE
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
 	WriteTW88( 0x08, 0x00 );					// Read count
	WriteTW88( 0x09, 0x00 );					// Read count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

//=============================================================================
//		SPI PageProgram
//=============================================================================
void SPI_PageProgram(DWORD spiaddr, BYTE *ptr, WORD cnt)
{
	WORD xaddr = (WORD)ptr;

	SPI_WriteEnable();

	WriteTW88( 0x03, DMAMODE_RW_XDATA );		// Mode = xdata -> SPI, Len=4
	WriteTW88( 0x0a, SPICMD_PROGRAM );			// SPI Command = PAGE_PROGRAM
	WriteTW88( 0x0b, spiaddr>>16 );				// SPI address
	WriteTW88( 0x0c, spiaddr>>8 );				// SPI address
	WriteTW88( 0x0d, spiaddr );					// SPI address
 	WriteTW88( 0x06, xaddr>>8 );				// Buffer address
	WriteTW88( 0x07, xaddr );					// Buffer address
 	WriteTW88( 0x08, cnt>>8 );					// Write count
	WriteTW88( 0x09, cnt );						// Write count
	WriteTW88( 0x1a, 0x00 );					// Read count

	WriteTW88( 0x04, 0x07 );					// DMA-Write start, Busy check
}

#endif





